package chapter08.s03threadsych;

/**
 * 背景：多线程的并发执行可以提高程序的效率，
 *      但是，当多个线程去访问同一个资源时，也会引发一些安全问题
 *      例如，当统计一个班级的学生数目时，如果有同学进进出出，则很难统计正确。
 *      为了解决这样的问题，需要实现多线程的同步，即限制某个资源在同一时刻只能被一个线程访问
 *
 *  售票案例，极有可能碰到“意外”情况，
 *      如一张票被打印多次，或者打印出的票号为0甚至负数。
 *      这些“意外”都是由多线程操作共享资源ticket所导致的线程安全问题
 *
 *  运行结果：最后打印售出的票出现了0和负数，这种现象是不应该出现的，
 *      因为售票程序中只有当票号大于0时才会进行售票。
 *      运行结果中之所以出现了负数的票号是因为多线程在售票时出现了安全问题。
 *
 *      原因是在售票程序的while循环中添加了sleep()方法
 *      当票号减为1时，休眠结束后，四个线程都会进行售票
 */
public class Example10 {
    public static void main(String[] args) {
        SaleThread saleThread = new SaleThread(); // 创建SaleThread对象
        // 创建并开启四个线程
        new Thread(saleThread, "线程一").start();
        new Thread(saleThread, "线程二").start();
        new Thread(saleThread, "线程三").start();
        new Thread(saleThread, "线程四").start();
    }
}

// 定义SaleThread类实现Runnable接口
class SaleThread implements Runnable {
    private int tickets = 10; // 10张票

    public void run() {
        while (tickets > 0) {
            try {
                Thread.sleep(10); // 经过此处的线程休眠10毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---卖出的票"
                    + tickets--);
        }
    }
}
